/*
 * ThreadPool.h
 *
 *  Created on: Jul 4, 2024
 *      Author: root
 */

#ifndef BSP_THREAD_THREADPOOL_H_
#define BSP_THREAD_THREADPOOL_H_

#include "basic_header.h"
namespace bsp {

class ThreadPool {
private:
	size_t thread_count;
	std::queue<std::function<void()>> funcs;

	std::mutex mtx;
	std::condition_variable con;
	bool quit;

	size_t max_que_size;

public:
	ThreadPool(size_t thread_count, size_t max_que_size) :
			thread_count { thread_count }, quit { false }, max_que_size {
					max_que_size } {

	}
	~ThreadPool() {
		close();
	}

	int open() {
		for (size_t i = 0; i < thread_count; i++) {
			std::thread([pool = this] {
				while (!pool->quit) {
					std::unique_lock<std::mutex> lock(pool->mtx);
					if (pool->funcs.size() == 0) {
						pool->con.wait(lock);
					}
					// pool size may be zero
					if (pool->funcs.size() > 0) {
						auto task = pool->funcs.front();
						pool->funcs.pop();
						lock.unlock();
						task();
					}
				}
			}).detach();

		}
		return 0;
	}

	void close() {
		quit = true;
		con.notify_all();
	}

//	template<class F>
//	void addFunc(F &&fn) {
//		std::lock_guard<std::mutex> lock(mtx);
//		ASSERT(funcs.size() < max_que_size, "");
//		funcs.emplace(std::forward<F>(fn));
//		con.notify_one();
//	}

	void addFunc(std::function<void()> fn) {
		std::lock_guard<std::mutex> lock(mtx);
		ASSERT(funcs.size() < max_que_size, "");
		funcs.push(fn);
		con.notify_one();
	}

	static void test1();

	static void test2();

};
}
#endif /* BSP_THREAD_THREADPOOL_H_ */
